/**
 * 
 */
package com.shy.base.util;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;

import com.alibaba.fastjson.JSONObject;
import com.shy.base.vo.AppConstants;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class LocationUtil {
	
	private final static String CSDN_API = "https://searchplugin.csdn.net/api/v1/ip/get?ip={}";
	
	private final static String AMAP_API = "https://restapi.amap.com/v3/ip?ip={}&output=json&key=ead02fe8d53e199ab5afcffb2e8bb62d";
	
	private final static String IP138_API = "https://www.ipshudi.com/{}.htm";
	
	private final static String COUNTRY_FLAG = "中国";
	
	private final static String[] DIRECT_CITY = new String[] {"北京", "上海", "天津", "重庆", "香港", "澳门"};
	
	private final static String[] PROVINCE_THREE = new String[] {"黑龙江", "内蒙古"};
	
	private final static String[] UNNORMAL_CITY = new String[] {"石景山", "门头沟", "浦东新区", "滨海新区", "黑龙江", "哈尔滨", "齐齐哈尔", "昂昂溪", "富拉尔基", "碾子山", "梅里斯", "牡丹江", "绥芬河", "佳木斯", "五大连池", "大兴安岭", "加格达奇", "乌伊岭", "金山屯", "乌马河", "汤旺河", "上甘岭", "杜尔伯特", "萨尔图", "让胡路", "七台河", "茄子河", "城子河", "双鸭山", "四方台", "公主岭", "梅河口", "通化县", "二道江", "苏家屯", "沈北新区", "瓦房店", "普兰店", "沙河口", "甘井子", "本溪县", "大石桥", "鲅鱼圈", "清河门", "辽阳县", "弓长岭", "太子河", "调兵山", "建平县", "双台子", "兴隆台", "葫芦岛", "内蒙古", "呼和浩特", "土左旗", "清水河", "白云鄂博", "满都拉", "土右旗", "达茂旗", "希拉穆仁", "昆都仑", "海勃湾", "乌兰察布", "察右前旗", "察右中旗", "察右后旗", "四子王旗", "舍伯吐", "科左中旗", "科左后旗", "青龙山", "扎鲁特", "科尔沁", "巴雅尔吐胡硕", "霍林郭勒", "阿鲁旗", "巴林左旗", "巴林右旗", "克什克腾", "翁牛特", "喀喇沁", "八里罕", "元宝山", "宝国图", "鄂尔多斯", "达拉特", "准格尔", "鄂前旗", "伊和乌素", "鄂托克", "杭锦旗", "乌审旗", "伊金霍洛", "乌审召", "康巴什", "巴彦淖尔", "乌前旗", "大佘太", "乌中旗", "乌后旗", "海力素", "那仁宝力格", "杭锦后旗", "锡林郭勒", "锡林浩特", "二连浩特", "阿巴嘎", "苏左旗", "苏右旗", "朱日和", "东乌旗", "西乌旗", "太仆寺", "镶黄旗", "正镶白旗", "正蓝旗", "博克图", "乌拉盖", "呼伦贝尔", "海拉尔", "小二沟", "阿荣旗", "莫力达瓦", "鄂伦春旗", "鄂温克旗", "新左旗", "新右旗", "满洲里", "牙克石", "扎兰屯", "额尔古纳", "图里河", "扎赉诺尔", "兴安盟", "乌兰浩特", "阿尔山", "科右中旗", "胡尔勒", "扎赉特", "科右前旗", "高力板", "阿拉善盟", "阿左旗", "阿右旗", "额济纳", "拐子湖", "吉兰太", "巴彦诺日公", "雅布赖", "乌斯太", "孪井滩", "石家庄", "井陉矿区", "高碑店", "张家口", "下花园", "承德县", "鹰手营子矿", "曹妃甸", "路��", "秦皇岛", "北戴河", "山海关", "雄安新区", "尖草坪区", "小店区", "杏花岭", "万柏林", "大同县", "五台县", "五台山", "成山头", "台儿庄", "东昌府", "乌鲁木齐", "小渠子", "沙依巴克", "达坂城", "水磨沟", "头屯河", "乌鲁木齐县", "西白杨沟", "克拉玛依", "乌尔禾", "白碱滩", "独山子", "石河子", "莫索湾", "呼图壁", "吉木萨尔", "玛纳斯", "蔡家湖", "吐鲁番", "托克逊", "巴音郭楞", "库尔勒", "巴音布鲁克", "铁干里克", "巴仑台", "阿拉尔", "阿克苏", "阿瓦提", "英吉沙", "塔什库尔干", "麦盖提", "岳普湖", "察布查尔", "尼勒克", "伊宁县", "特克斯", "霍尔果斯", "和布克赛尔", "巴里坤", "阿勒泰", "哈巴河", "吉木乃", "布尔津", "阿图什", "阿克陶", "阿合奇", "博尔塔拉", "阿拉山口", "图木舒克", "五家渠", "铁门关", "可克达拉", "堆龙德庆", "墨竹工卡", "日喀则", "南木林", "聂拉木", "谢通门", "桑珠孜", "浪卡子", "工布江达", "类乌齐", "狮泉河", "曲麻莱", "德令哈", "大柴旦", "格尔木", "七里河", "阿克塞", "张家川", "积石山", "嘉峪关", "石嘴山", "大武口", "红寺堡", "青铜峡", "沙坡头", "平顶山", "禹王台", "驻马店", "三门峡", "雨花台", "张家港", "淮阴区", "清江浦", "淮安区", "连云港", "东西湖", "老河口", "梁子湖", "西塞山", "黄石港", "伍家岗", "丹江口", "神农架", "龙子湖", "芜湖县", "田家庵", "谢家集", "八公山", "马鞍山", "黄山区", "黄山风景区(光明顶)", "九华山", "武夷山", "钓鱼岛", "南昌县", "青云谱", "青山湖", "共青城", "上饶县", "吉安县", "井冈山", "景德镇", "湘江新区", "长沙县", "衡阳县", "赫山区", "冷水江", "邵阳县", "岳阳楼区", "张家界", "武陵源", "冷水滩", "观山湖", "红花岗", "黔东南", "七星关", "六盘水", "黔西南", "龙泉驿", "都江堰", "青白江", "攀枝花", "自流井", "龙马潭", "宜宾县", "峨眉山", "五通桥", "金口河", "峨眉山市", "九寨沟", "马尔康", "若尔盖", "太华山", "麻栗坡", "香格里拉", "西双版纳", "西乡塘", "金城江", "涠洲岛", "铁山港", "防城港", "五指山", "黄岩岛", "氹仔岛", "路环岛"};
	

	/**
	 * 通过csdn查询信息
	 * @param ip
	 * @return
	 */
	public static Map<String, String> getIpInfoByCsdn(String ip){
		Map<String, String> result = new HashMap<>();
		result.put("ip", ip);
		try {
			String url = StrUtil.format(CSDN_API, ip);
			HttpRequest request = HttpRequest.get(url);
			request.header("User-Agent", RandomUtil.randomEle(AppConstants.USERAGENT));
			String resultJson = request.execute().body();
			JSONObject json = JSONObject.parseObject(resultJson);
			if (json.containsKey("code") && "200".equals(json.getString("code"))) {
				String address = json.getJSONObject("data").getString("address").replace(COUNTRY_FLAG, "").trim();
				List<String> addressPart = Arrays.asList(address.split(" "));
				result.put("province", convertProvince(addressPart.get(0)));
				if (addressPart.size() > 2) {
					result.put("city", convertCity(addressPart.get(1)));
				}
				if (addressPart.size() > 3) {
					result.put("county", convertCity(addressPart.get(2)));
				}
				result.put("isp", convertProvince(addressPart.get(addressPart.size() - 1)));
				
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage());
		}
		return result;
	}
	
	/**
	 * 通过高德查询信息
	 * @param ip
	 * @return
	 */
	public static Map<String, String> getIpInfoByAmap(String ip){
		Map<String, String> result = new HashMap<>();
		result.put("ip", ip);
		try {
			String url = StrUtil.format(AMAP_API, ip);
			HttpRequest request = HttpRequest.get(url);
			request.header("User-Agent", RandomUtil.randomEle(AppConstants.USERAGENT));
			String resultJson = request.execute().body();
			JSONObject json = JSONObject.parseObject(resultJson);
			if (json.containsKey("status") && "1".equals(json.get("status"))) {
				result.put("province", convertProvince(json.getString("province")));
				result.put("city", convertCity(json.getString("city")));
			}
		} catch (Exception e) {
			//e.printStackTrace();
			log.error(e.getMessage());
		}
		return result;
	}
	
	
	/**
	 * 通过ip138查询信息
	 * @param ip
	 * @return
	 */
	public static Map<String, String> getIpInfoBy138(String ip){
		Map<String, String> result = new HashMap<>();
		result.put("ip", ip);
		try {
			String url = StrUtil.format(IP138_API, ip);
			HttpRequest request = HttpRequest.get(url);
			request.header("User-Agent", RandomUtil.randomEle(AppConstants.USERAGENT));
			String resultStr = request.execute().body();
			Document doc = Jsoup.parse(resultStr);
			Elements trs = doc.select(".ft tr");
			String detail = trs.get(1).select("span").get(0).text();
			detail = detail.replace(COUNTRY_FLAG, "").trim();
			String[] areas = detail.split(" ");
			Elements citys = trs.get(1).select("span").get(0).select("a");
			result.put("detail", detail);
			result.put("province", convertProvince(areas[0]));
			if (areas.length > 1) {
				String county = areas[areas.length - 1];
				result.put("county", convertCity(county));
				if (citys.size() > 0) {
					String city = citys.get(0).text();
					if (county.equals(city)) {
						result.put("county", null);
					}
					result.put("city", convertCity(city));
				} else if (Arrays.asList(DIRECT_CITY).contains(convertProvince(areas[0]))){
					result.put("city", convertProvince(areas[0]));
				}
			}
			if (trs.size() > 2) {
				String isp = trs.get(2).select("td").get(1).text();
				result.put("isp", isp);
			}
		} catch (Exception e) {
			//e.printStackTrace();
			log.error(e.getMessage());
		}
		return result;
	}
	
	/**
	 * 获取ip信息
	 * @param ip
	 * @return
	 */
	public static Map<String, String> getIpAddress(String ip){
		Map<String, String> result = getIpInfoByCsdn(ip);
		if (result.size() < 3) {
			result = getIpInfoByAmap(ip);
		} else if (result.size() < 3) {
			result = getIpInfoBy138(ip);
		}
		return result;
	}
	
	
	/**
	 * 省份处理
	 * @param province
	 * @return
	 */
	private static String convertProvince(String province) {
		List<String> provinceThreeList = Arrays.asList(PROVINCE_THREE);
		for (String provinceThree : provinceThreeList) {
			if (province.contains(provinceThree)) {
				return provinceThree;
			}
		}
		return province.substring(0, 2);
	}
	
	/**
	 * 城市处理
	 * @param city
	 * @return
	 */
	private static String convertCity(String city) {
		List<String> unNormalList = Arrays.asList(UNNORMAL_CITY);
		for (String string : unNormalList) {
			if (city.indexOf(string) >= 0) {
				return string;
			}
		}
		return city.length() > 1 ? city.substring(0, 2) : city;
	}
	
	
	public static void main(String[] args) {
		//System.out.println(getIpInfoByCsdn("61.163.157.161"));
		//System.out.println(getIpInfoByAmap("61.163.157.161"));
		System.out.println(getIpInfoBy138("123.233.44.197"));
		/*System.out.println(getIpInfoBy138("183.226.156.97"));
		System.out.println(getIpInfoBy138("223.104.68.40"));
		System.out.println(getIpInfoBy138("120.228.139.123"));
		System.out.println(getIpInfoBy138("112.9.38.182"));
		System.out.println(getIpInfoBy138("223.104.236.38"));
		System.out.println(getIpInfoBy138("124.116.252.7"));
		System.out.println(getIpInfoBy138("115.60.135.93"));
		System.out.println(getIpInfoBy138("60.207.88.81"));
		System.out.println(getIpInfoBy138("114.84.152.76"));
		System.out.println(getIpInfoBy138("218.69.226.173"));
		System.out.println(getIpInfoBy138("120.244.20.84"));
		System.out.println(getIpInfoBy138("120.205.8.180"));
		System.out.println(getIpInfoBy138("111.49.122.8"));
		System.out.println(getIpInfoBy138("36.100.44.172"));
		System.out.println(getIpInfoBy138("49.215.252.40"));
		System.out.println(getIpInfoBy138("60.246.162.87"));*/
		
		
	}
	
}
